package com.itc.bi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itc.bi.constant.SystemConstant;
import com.itc.bi.entity.DatasourceEntity;
import com.itc.bi.handler.DatasourceHandler;
import com.itc.bi.handler.DatasourceJdbcPool;
import com.itc.bi.mapper.DatasourceMapper;
import com.itc.bi.mapper.DirectDataSetMapper;
import com.itc.bi.query.DatasourceQuery;
import com.itc.bi.service.DatasourceService;
import com.itc.bi.service.TableService;
import com.itc.common.core.exception.CheckedException;
import com.itc.common.core.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class DatasourceServiceImpl extends ServiceImpl<DatasourceMapper, DatasourceEntity> implements DatasourceService {

    @Lazy
    @Autowired
    TableService tableService;
    @Autowired
    DirectDataSetMapper directDataSetMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(DatasourceEntity entity){

        if(StringUtils.equalsAny(entity.getType(),SystemConstant.DATASOURCE_TYPE_GAUSSDB,SystemConstant.DATASOURCE_TYPE_PG)){
            if(StringUtils.isNotBlank(entity.getSchemaName()) && entity.getJdbcUrl().indexOf("currentSchema") >0 ){
                throw new ServiceException("模式冲突,url中已存在");
            }
        }

        LambdaQueryWrapper<DatasourceEntity> qw = Wrappers.lambdaQuery();
        qw.eq(DatasourceEntity::getName,entity.getName());
        DatasourceEntity old = getOne(qw);
        if(null != old && !old.getId().equals(entity.getId())){
            throw new CheckedException("名称已存在，请检查");
        }
        //初始化表结构标志，新增或修改url时初始化
        boolean initTableFlag = false;
        if(null != entity.getId()){
            DatasourceJdbcPool.remove(entity.getId());
            old = getById(entity.getId());
            if(null == old){
                throw new ServiceException("记录不存在");
            }

            //判断是否需要初始化表信息
            //mysql判断?前是否有变化
            //oracle判断用户和url是否有变化
            //pg判断模式
            int index = entity.getJdbcUrl().indexOf("?");
            index  = index > 0 ? index : entity.getJdbcUrl().length();

            int oldIndex = old.getJdbcUrl().indexOf("?");
            oldIndex  = oldIndex > 0 ? oldIndex : old.getJdbcUrl().length();
            if(!old.getJdbcUrl().substring(0,oldIndex).equals(entity.getJdbcUrl().substring(0,index))){
                initTableFlag = true;
            }
            if(!initTableFlag && SystemConstant.DATASOURCE_TYPE_ORACLE.equals(entity.getType())){
                if(!old.getJdbcUrl().equals(entity.getJdbcUrl()) || !old.getUserName().equals(entity.getUserName())){
                    initTableFlag = true;
                }
            }
            if(!initTableFlag && StringUtils.equalsAny(entity.getType(),SystemConstant.DATASOURCE_TYPE_GAUSSDB,SystemConstant.DATASOURCE_TYPE_PG)){
                String newSchema = schema(entity);
                String oldSchema = schema(old);
                if(!newSchema.equals(oldSchema)){
                    initTableFlag = true;
                }
            }
            if(initTableFlag){
                int num = directDataSetMapper.getCountByDsId(entity.getId());
                if(num > 0){
                    throw new ServiceException("数据源已经绑定数据集,不能修改");
                }
            }
        }else{
            initTableFlag=true;
            try {
                //获取数据库版本号
                entity.setVersion(DatasourceHandler.datasourceFactory(entity).getVersion());
            }catch (Exception e){}
        }
        super.saveOrUpdate(entity);
        //初始化表和表字段信息
        if(initTableFlag){
            tableService.initTable(entity);
        }
        return true;
    }

    @Override
    public List<DatasourceEntity> list(){
        LambdaQueryWrapper<DatasourceEntity> qw = Wrappers.lambdaQuery();
        qw.orderBy(true,false,DatasourceEntity::getCreateTime);
        return super.list(qw);
    }

    public Page page(DatasourceQuery query){
        int pageIndex = 1;
        int pageSize = 10;
        if(null != query.getPageIndex() && null != query.getPageSize()){
            pageIndex = query.getPageIndex() > 0 ? query.getPageIndex() : 1;
            pageSize = query.getPageSize() > 0 ? query.getPageSize() : 10;
        }
        LambdaQueryWrapper<DatasourceEntity> qw = Wrappers.lambdaQuery();
        qw.like(StringUtils.isNotBlank(query.getName()),DatasourceEntity::getName,query.getName());
        qw.eq(StringUtils.isNotBlank(query.getType()),DatasourceEntity::getType,query.getType());
        qw.orderBy(true,false,DatasourceEntity::getCreateTime);
        return page(new Page<DatasourceEntity>(pageIndex,pageSize),qw);
    }

    @Override
    public void buildExInfo(DatasourceEntity data) {
    }
    @Override
    public void buildExInfo(List<DatasourceEntity> list) {
    }

    @Override
    public void connect(DatasourceEntity entity){
        entity.setId(null);
        DatasourceHandler.datasourceFactory(entity).closeConn();
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(Long id){
        //判断数据源是否创建了数据集,已创建数据集的数据源不能删除
        int count = directDataSetMapper.getCountByDsId(id);
        if(count > 0){
            throw new CheckedException("数据源已创建数据集，不能删除，请先删除数据集");
        }
        //删除数据源下的表和字段数据
        tableService.deleteByDatasourceId(id);
        super.removeById(id);
        DatasourceJdbcPool.remove(id);
        return true;
    }

    @Override
    public List<String> getSchema(DatasourceEntity entity){
        if(!StringUtils.equalsAny(entity.getType(), SystemConstant.DATASOURCE_TYPE_PG,SystemConstant.DATASOURCE_TYPE_GAUSSDB)){
            throw new CheckedException("此类型数据库不支持");
        }
        entity.setId(null);
        try {
            //jdbc查询模式
            DatasourceHandler datasource = DatasourceHandler.datasourceFactory(entity);
             List<String> list = datasource.getSchema();
            datasource.closeConn();
            return list;
        }catch (Exception e){
            throw new ServiceException("获取模式失败，异常信息："+e.getMessage());
        }
    }

    public DatasourceEntity getDecodeData(Long id){
        DatasourceEntity entity = getById(id);
        if(null == entity){
            throw new ServiceException("数据源不存在");
        }
        return entity;

    }

    public String schema(DatasourceEntity entity){
        String schema = entity.getSchemaName();
        if(StringUtils.isBlank(schema)){
            int index = entity.getJdbcUrl().indexOf("currentSchema");
            if( index > 0){
                String url = entity.getJdbcUrl().substring(index+1);
                index  = url.indexOf("?");
                index = index>0 ?index:url.length();
                schema = url.substring(0,index);
            }else{
                schema = "public";
            }
        }
        return schema;
    }
}
